/**
 * Copyright (C) 2012 Oleg Anastassov <o.anastasov@gmail.com>
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package kz.kstu.ent.desktop.components;

import kz.kstu.ent.util.logger.Logger;

import javax.swing.*;
import javax.swing.table.TableCellEditor;
import javax.swing.text.JTextComponent;
import javax.swing.text.MaskFormatter;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.List;

/**
 * @author Oleg Anastassov
 */
public final class CellEditorFactory {

    private static final Logger LOGGER = Logger.getLogger(CellEditorFactory.class);
    private static final String DATE_MASK = "##'.##'.####";

    private CellEditorFactory() {
    }

    public static TableCellEditor createSelectionCellEditor() {
        JTextField textField = new JTextField();
        textField.addFocusListener(new SelectFocusListener());
        return new DefaultCellEditor(textField);
    }

    public static TableCellEditor createNumberCellEditor(boolean isFloat, boolean availableNegative) {
        JTextField textField = new JTextField();
        textField.addFocusListener(new SelectFocusListener());
        textField.addKeyListener(new DigitKeyListener(isFloat, availableNegative));
        return new DefaultCellEditor(textField);
    }

    public static TableCellEditor createDateCellEditor() {
        try {
            JFormattedTextField formattedTextField = new JFormattedTextField(new MaskFormatter(DATE_MASK));
            formattedTextField.addFocusListener(new SelectFocusListener());
            return new DefaultCellEditor(formattedTextField);
        } catch (ParseException e) {
            LOGGER.error(e.getMessage(), e);
            return new DefaultCellEditor(new JTextField());
        }
    }

    public static TableCellEditor createComboBoxCellEditor(List<?> objects) {
        JComboBox comboBox = new JComboBox(objects.toArray());
        return new DefaultCellEditor(comboBox);
    }

    private static class SelectFocusListener extends FocusAdapter {
        @Override
        public void focusGained(FocusEvent e) {
            JTextComponent component = (JTextComponent) e.getSource();
            component.selectAll();
        }
    }

    private static class DigitKeyListener extends KeyAdapter {
        private boolean isFloat;
        private boolean availableNegative;
        private char decimalSeparator;

        public DigitKeyListener() {
        }

        public DigitKeyListener(boolean isFloat, boolean availableNegative) {
            this.isFloat = isFloat;
            this.availableNegative = availableNegative;

            DecimalFormat format = (DecimalFormat) DecimalFormat.getInstance();
            DecimalFormatSymbols symbols = format.getDecimalFormatSymbols();
            decimalSeparator = symbols.getDecimalSeparator();
        }

        @Override
        public void keyTyped(KeyEvent e) {
            char character = e.getKeyChar();
            if (!Character.isDigit(character)) {
                if (!((isFloat && character == decimalSeparator)
                        || (availableNegative && character == '-'))) {
                    e.consume();
                }
            }
        }
    }

    private static class MaxLengthKeyListener extends KeyAdapter {
        private int maxLength;

        public MaxLengthKeyListener(int maxLength) {
            this.maxLength = maxLength;
        }

        @Override
        public void keyTyped(KeyEvent e) {
            JTextComponent textComponent = (JTextComponent) e.getSource();
            int selectedTextLength = textComponent.getSelectionEnd() - textComponent.getSelectionStart();
            if (textComponent.getText().length() >= maxLength && selectedTextLength == 0) {
                e.consume();
            }
        }
    }
}


